home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / General App Samples / QDGX Shell ƒ / QDGX shell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-20  |  12.2 KB  |  421 lines  |  [TEXT/MMCC]

  1. /**\
  2. |**| =====================================================================
  3. |**|
  4. |**|    QDGX shell.c
  5. |**|
  6. |**|    This file is a shell that can be used to build "new" Graphics 
  7. |**|    applications.  It contains all of the required calls to use the "new"
  8. |**|    Graphics routines and QuickDraw (i.e. windows) together. It can put up
  9. |**|    one or more window.  This shell also supports GX printing.
  10. |**|
  11. |**|    The application is expected to supply the following functions which
  12. |**|    are called by this shell:
  13. |**|        void  DoSetup (void);
  14. |**|        void  DoDraw (WindowPtr);
  15. |**|        OSErr DoCreateNew (void);
  16. |**|        void  DoDispose (WindowPtr);
  17. |**|        void  DoIdle (WindowPtr);
  18. |**|        void  DoTeardown (void);
  19. |**|        void  DoClick (WindowPtr, Point);
  20. |**|
  21. |**|
  22. |**|    Change History:
  23. |**|        3/90    New
  24. |**|        6/91    PLA  Updated the shell to reflect the changes in
  25. |**|                     "Graphics" v1.0d21.2.
  26. |**|        6/92         Made the following variables global: gDebugging,
  27. |**|                     gGiveMeValidation,gGraphicsHeapSize.
  28. |**|                     See the comments for detail in this file.
  29. |**|        6/92    DMH  Added printing guts, mangled and reorganized.
  30. |**|        9/93    PLA  Updated files to work with the ß2 "GXified"
  31. |**|                     interface files.
  32. |**|        9/93    DMH  Added override for gxPrintingEvent to handle
  33. |**|                     update events.
  34. |**|        9/93    DMH  Added GXUpdateJob for resume events.
  35. |**|        12/93    MD   Extensive changes made for clarity, shell-like
  36. |**|                     ability, cleanliness.
  37. |**|        8/94    DH   More changes made for universal header and clarity
  38. |**|        7/95    DH   More changes made for universal headers 2.1
  39. |**|        6/96    cn   Updated to support MPW Pro #19.
  40. |**|
  41. |**|    ©1992-1996  Apple Computer, Inc.
  42. |**|    All rights reserved.
  43. |**|
  44. |**| =====================================================================
  45. \**/
  46.  
  47.  
  48. #include "QDGX shell.h"
  49.  
  50.  
  51. /**\
  52. |**| ---------------------------------------------------------------------
  53. |**| GLOBALS
  54. |**| ---------------------------------------------------------------------
  55. \**/
  56. Boolean            gQuitting = false;
  57. long            gSleep = 0;
  58.  
  59. #if !defined(__MWERKS__) && !defined(__THINKC__)
  60. QDGlobals        qd;
  61. #endif
  62.  
  63.  
  64.  
  65.  
  66. /**\
  67. |**| ---------------------------------------------------------------------
  68. |**| main()
  69. |**| ---------------------------------------------------------------------
  70. \**/
  71. void main()
  72. {        
  73.     CursHandle            theCurs; 
  74.     Handle                menuBar;
  75.     OSErr                err;
  76.     WindowPtr            wind;
  77.     gxGraphicsClient     client;
  78.     
  79.     InitToolbox();
  80.  
  81.     theCurs = GetCursor(watchCursor);
  82.     SetCursor(*theCurs);
  83.  
  84.     menuBar = GetNewMBar(rMenuBar); // Create the menu bar.
  85.     SetMenuBar(menuBar);
  86.     DisposeHandle(menuBar);
  87.  
  88.     CheckQuickDrawGX();
  89.     if (gQuitting)
  90.     {
  91.         SetCursor(&qd.arrow);
  92.         (void) StopAlert(rNoQuickDrawGXID, NULL);
  93.         return;
  94.     }
  95.     
  96.     
  97.     // Before starting to draw, we'll call the DoSetup routine so we can initialize any
  98.     // global variables or behaviors.  This routine would be a good time to change the
  99.     // gGraphicsHeapSize variable before we make the new graphics client next.
  100.  
  101.     DoSetup();
  102.     
  103.     
  104.     // The GXNewGraphicsClient routine defines the graphics heap size.  If you do not make this
  105.     // call, the GX graphics engine will create this heap automatically.  How?  It will create
  106.     // a heap which is a percentage of your application's ideal memory foot print.  This call
  107.     // allows you to explicity define the ammount of memory used by the graphics system for
  108.     // its graphics objects heap.
  109.  
  110.     client = GXNewGraphicsClient(nil, gGraphicsHeapSize * 1024, 0L);
  111.  
  112.     if ( client )
  113.     {
  114.         // If debugging is #define'd, you will receive graphics library errors & notices will be posted.
  115.         // This functionality will only work with the "debugging" version of QuickDraw GX.  If you
  116.         // don't have the debugging version installed, these functions will not work. 
  117.     
  118. #ifdef debugging
  119.             SetGraphicsLibraryErrors ();
  120.             SetGraphicsLibraryNotices();    
  121. #endif
  122.     
  123.         // Set gGiveMeValidation to TRUE if you want run-time validation. As you increase the amount
  124.         // of validation, The drawing speed will SLOW down due to all of the internal checking. 
  125.             
  126.         // gxPublicValidation will check parameters to public routines. For additional details
  127.         // regarding the various levels of validation, see "Inside Macintosh: QuickDraw GX
  128.         // Environment and Utilties."
  129.     
  130.         if (gGiveMeValidation)
  131.             GXSetValidation(gxPublicValidation); 
  132.     
  133.     
  134.         // Initialize the new graphics and printing environments.
  135.     
  136.         if ( GXGetGraphicsError( nil ) != out_of_memory ) 
  137.         {
  138.             GXEnterGraphics();
  139.             err = GXInitPrinting();
  140.         
  141.             // Initialize the other managers, if no errors occurred.
  142.             
  143.             if ( err == noErr )
  144.             {
  145.                 gQuitting = false;
  146.                 AddResMenu(GetMHandle(mApple), 'DRVR'); // add Apple Menu items.
  147.                 DrawMenuBar();
  148.     
  149.                 // We initialize the CommonColors Library.  This will allow us to set the color of a
  150.                 // shape by calling the SetShapeCommonColor function. We will need to call
  151.                 // DisposeCommonColors when we leave, to clean up the world.
  152.     
  153.                 InitCommonColors();
  154.         
  155.                 DoCreateNew();
  156.                 
  157.                 SetCursor(&qd.arrow);  
  158.                 
  159.                 while (!gQuitting)
  160.                     EventLoop();
  161.     
  162.                 // Leaving.  Close all the windows so we get rid of any data we or GX created.  Then,
  163.                 // dispose of the common colors and exit the GX printing and graphics environment.
  164.     
  165.                 while ( (wind = FrontWindow()) != NULL )
  166.                     DoDispose(wind);
  167.     
  168.                 DisposeCommonColors();
  169.                 GXExitPrinting();    // Close the new printing mgr. 
  170.             }
  171.             
  172.             GXExitGraphics();        // Deallocate all of the default structures
  173.             
  174.         } else   DebugStr ("\p Unfortunately, there is not enough memory for GX, please quit an app...");                
  175.     }  else   DebugStr ("\p Unfortunately, there is not enough memory for GX, please quit an app...");
  176.     
  177.     GXDisposeGraphicsClient(client);
  178.     DoTeardown();            // Dispose of any global variables we made in DoSetup.
  179. }
  180.  
  181.  
  182. /**\
  183. |**| ---------------------------------------------------------------------
  184. |**| InitToolbox()
  185. |**| ---------------------------------------------------------------------
  186. \**/
  187. void InitToolbox (void)
  188. {
  189.     // Generic heap initialization.
  190.     
  191.     MaxApplZone(); 
  192.     MoreMasters(); MoreMasters(); MoreMasters(); 
  193.     MoreMasters(); MoreMasters(); MoreMasters(); 
  194.     
  195.     // Start up the toolbox so we can notify people if there's a problem
  196.     
  197.     InitGraf(&qd.thePort);
  198.     InitFonts();
  199.     InitWindows();
  200.     InitMenus();
  201.     TEInit();
  202.     InitDialogs(nil);
  203.     InitCursor();
  204. }
  205.  
  206.  
  207. /**\
  208. |**| ---------------------------------------------------------------------
  209. |**| CheckQuickDrawGX()
  210. |**| Before making any calls, we'll see if QuickDraw GX is available.
  211. |**| If it's not, then set gQuitting=true so we can avoid doing any of 
  212. |**| the rest of this application.
  213. |**| ---------------------------------------------------------------------
  214. \**/
  215. void CheckQuickDrawGX (void)
  216. {
  217.     long                theFeature;
  218.  
  219.     // Before making any calls, we'll see if QuickDraw GX is available.  If it's not,
  220.     // we'll avoid doing any of the rest of this application
  221.     
  222.     if ( (Gestalt(gestaltGraphicsVersion, &theFeature) != noErr) ||
  223.           (Gestalt(gestaltGXPrintingMgrVersion, &theFeature) != noErr))
  224.         gQuitting = true;   // QuickDraw GX is not available
  225.     
  226. #ifdef powerc
  227.     // This is a sanity check to see if the PowerPC QuickDrawGXLib is installed.
  228.     // Since we are "weak" linked to QuickDrawGXLib, the Process Manager will
  229.     // launch us even if QuickDrawGXLib is missing.  If it's missing, the
  230.     // Code Fragment Manager will leave the address of the functions we call
  231.     // unresolved, and we would crash if we tried to call that function.  So,
  232.     // we do a check here and should be prepared to exit gracefully if the 
  233.     // library is missing.  This could happen if the user has installed a
  234.     // 68K only version of QuickDraw GX.  It could also happen if the user has
  235.     // taken the QuickDraw GX extension out of the Extensions Folder.  
  236.     //
  237.     // Note - We could check this against any function we call in the library.
  238.     // GXNewGraphicsClient is the first function we call, so it's convenient.
  239.  
  240.     if ( (long)GXNewGraphicsClient == kUnresolvedSymbolAddress ) 
  241.         gQuitting = true;   // QuickDraw GX is not available in Power Mac
  242. #endif
  243. }
  244.  
  245.  
  246. /**\
  247. |**| ---------------------------------------------------------------------
  248. |**| MyPrintingEventOverride()
  249. |**| Override for GXPrintingEvent.  It allows us to update our windows
  250. |**| when the moveable modal printing dialogs are moved.  Keep this in your
  251. |**| main segment, which will always be loaded when GX tries to call the routine.
  252. |**| ---------------------------------------------------------------------
  253. \**/
  254. OSErr MyPrintingEventOverride (EventRecord *event, Boolean filterEvent)
  255. {
  256.     // Handle events in whatever way is appropriate.
  257.     // MyDoEvent is our generic event handler.
  258.  
  259.     if ( !filterEvent )
  260.         MyDoEvent(event);
  261.     return noErr;
  262. }
  263.  
  264.  
  265. /**\
  266. |**| ---------------------------------------------------------------------
  267. |**| EventLoop()
  268. |**| ---------------------------------------------------------------------
  269. \**/
  270. void EventLoop ()
  271. {
  272.     EventRecord event;
  273.  
  274.     if ( WaitNextEvent(everyEvent, &event, gSleep, nil) )
  275.         MyDoEvent(&event);
  276.     else
  277.         DoIdle(FrontWindow());
  278. }
  279.  
  280.  
  281.  
  282. /**\
  283. |**| ---------------------------------------------------------------------
  284. |**| IsAppWindow()
  285. |**| This routine looks to make sure a window pointer is not nil and that
  286. |**| the window it points to is of kind userKind.  If it is, it returns
  287. |**| true, else it returns false.
  288. |**| ---------------------------------------------------------------------
  289. \**/
  290. Boolean IsAppWindow (WindowPtr wind)
  291. {
  292.     return    ((((WindowPeek) wind)->windowKind == userKind) && (wind != nil));
  293. }
  294.  
  295.  
  296. /**\
  297. |**| ---------------------------------------------------------------------
  298. |**| MyDoEvent()
  299. |**| ---------------------------------------------------------------------
  300. \**/
  301. void MyDoEvent (EventRecord *event)
  302. {
  303.     char            key;
  304.     WindowPtr         window;        // temporarily used to hold 
  305.     GrafPtr            oldPort;
  306.     unsigned long    mssg;
  307.  
  308.     mssg = event->message;
  309.     switch(event->what)
  310.     {                    
  311.         case mouseDown:
  312.             DoMouseDown(event);
  313.             break;
  314.  
  315.         case keyDown:
  316.         case autoKey:
  317.             key = mssg & charCodeMask;
  318.             if ( event->modifiers & cmdKey )
  319.                 if ( event->what == keyDown )
  320.                     DoMenuCommand(MenuKey(key));
  321.             break;
  322.  
  323.         case updateEvt:
  324.             window = (WindowPtr)mssg;
  325.             if ( IsAppWindow(window) )
  326.             {
  327.                 GetPort(&oldPort);
  328.                 SetPort(window);
  329.                 BeginUpdate(window);
  330.                 DoDraw(window, true);
  331.                 EndUpdate(window);
  332.                 SetPort(oldPort);
  333.             }
  334.             break;
  335.         
  336.         case activateEvt:
  337.             break;
  338.         
  339.         case osEvt:
  340.             if ( (mssg>>24)                        // if high byte of message indicates
  341.                     == suspendResumeMessage )    // this is suspend/resume event
  342.             {
  343.                 if (mssg & resumeFlag)            // if resume event
  344.                 {                                // we're switching back from another app so..
  345.                     gSleep = 0;                    // speed up  
  346.  
  347.                     // On a resume event, we need to call GXUpdateJob on all of our
  348.                     // documents' jobs.  This is important because the user may have
  349.                     // just changed something which affects our jobs (like the size
  350.                     // of the paper in the printer).
  351.                     //
  352.                     // Since our application stores our document references in the refCon fields
  353.                     // of our documents' windows, we just loop through every one of our windows,
  354.                     // extract our document pointers and update the associated jobs.
  355.         
  356.                     window = FrontWindow();
  357.                     while (window != nil)
  358.                     {
  359.                         if ( IsAppWindow(window) )
  360.                             GXUpdateJob(GetDocJob(window));
  361.                         window = (WindowPtr) ((WindowPeek) window)->nextWindow;
  362.                     }
  363.                 }
  364.                 else                            // if suspend event
  365.                     gSleep=80;                    // we're switching to another app so slow down...
  366.             }
  367.             break;
  368.     }
  369. }
  370.  
  371.  
  372. /**\
  373. |**| ---------------------------------------------------------------------
  374. |**| DoMouseDown
  375. |**| handle DoMouseDown events
  376. |**| ---------------------------------------------------------------------
  377. \**/
  378. void DoMouseDown (EventRecord *event)
  379. {
  380.     WindowPtr   window;
  381.     short       clickArea;
  382.     Rect        screenRect;
  383.  
  384.     clickArea = FindWindow( event->where, &window );
  385.     switch (clickArea)
  386.     {
  387.         case inSysWindow:
  388.             SystemClick(event, window);
  389.             break;
  390.                         
  391.         case inDrag:
  392.             screenRect = (**GetGrayRgn()).rgnBBox;
  393.             if ( IsAppWindow(window) )
  394.                 DragWindow( window, event->where, &screenRect );
  395.             break;
  396.  
  397.         case inContent:
  398.             if (IsAppWindow(window))
  399.             {
  400.                 if ( window == FrontWindow())
  401.                     DoClick(window, event->where);
  402.                 else
  403.                      SelectWindow(window);
  404.             }
  405.             break;
  406.         
  407.         case inGoAway:
  408.             if ( IsAppWindow(window) )
  409.             {
  410.                 if ( TrackGoAway(window, event->where) )
  411.                     DoDispose(window);
  412.             }
  413.             break;
  414.         
  415.         case inMenuBar:
  416.             DoMenuCommand(MenuSelect(event->where));
  417.             break;
  418.  
  419.     }
  420. }
  421.